Crate fs_at

source ·
Expand description

Extension for operations that manipulate the file system relative to an open directory, rather than the global namespace.

NB: If a missing capability or platform is found, I will happily add / accept patches : features are being added as needed, rather than speculatively.

The Rust standard library does not (yet) offer at-style filesystem calls as a core feature. For instance mkdirat. These calls are essential for writing race-free filesystem code, since otherwise the state of the filesystem path that operations are executed against can change silently, leading to TOC-TOU race conditions. For Unix these calls are readily available in the libc crate, but for Windows some more plumbing is needed. This crate provides a unified Rust-y interface to these calls.

Not all platforms behave identically in their underlying syscalls, and this crate doesn’t abstract over fundamental differences, but it does attempt to provide consistent errors for key scenarios. As a concrete example creating a directory at the path of an existing link with follow disabled errors with AlreadyExists. In general platform documentation should be consulted to understand the underlying behaviour.

On Linux this is achieved by reading back the path that was requested, as atomic mkdir isn’t yet available. mkdirat is used so the parent directory is reliable, but the presence of a link pointing to another part of the file system cannot be precluded.

On Windows this same scenario will either result in fs_at receiving a NotADirectory error from NtCreateFile, or the open succeeding but a race-free detection of the presence of the link is done using DeviceIoControl. Both cases are reported as AlreadyExists. The two codepaths exist because on Windows symlinks can themselves be files or directories, and the kernel type-checks some operations such as creating a directory or truncating a file at both the link target and the link source.

Truncate+nofollow also varies by platform: See OpenOptions::truncate.

Caveats:

  • On windows, procmon will cause the symlink resolution check to receive an incorrect error code. Enabling the workaround-procmon feature and setting FS_AT_WORKAROUND_PROCMON will treat ACCESS_DENIED as ERROR_NOT_REPARSE_POINT. https://twitter.com/rbtcollins/status/1617211985384407044

Feature flags:

  • workaround-procmon: enables the FS_AT_WORKAROUND_PROCMON environment variable.
  • log: enables trace log messages for debugging

Modules§

Structs§

  • The returned type for each entry found by read_dir.
  • Similar to std::fs::OpenOptions, this struct is used to parameterise the various at functions, which are then called on the struct itself. Typical use is to create a struct via Default::default or OpenOptions::default(), and then customise it as desired (e.g. setting security descriptors on windows, or mode on unix) using an appropriate platform specific trait, finishing up with the desired manipulation e.g. mkdirat.
  • Iterate over the contents of a directory. Created by calling read_dir() on an opened directory. Each item yielded by the iterator is an io::Result to allow communication of io errors as the iterator is advanced.

Enums§

  • File kind indicator
  • Controls the way writes to an opened file are performed. Write modes do not affect how the file is opened - creating the file or truncating it require separate options.

Functions§

  • Read the children of the directory d.